// SPDX-License-Identifier: GPL-2.0

#include <linux/types.h>
#include <mach/common.h>

#if !IS_ENABLED(CONFIG_ARCH_LOMBO_N5)
#include <mach/efuse.h>
#endif

#include <linux/slab.h>
#include <linux/mm.h>

#include "phy-nx-usb.h"
#include "phy-nx-usb-reg.h"

int lb_nx_usbphy_suspend(void __iomem *reg_base)
{
	int			ret = 0;
	void __iomem		*reg_addr;
	reg_usb_usbctrl_t	usb_ctrl_reg;

	reg_addr = reg_base + USBCTRL;

	/* force phy into suspend and close phy clock */
	usb_ctrl_reg.val = READREG32(reg_addr);
	usb_ctrl_reg.bits.susp_sel = 1;
	usb_ctrl_reg.bits.susp = 0;
	WRITEREG32(reg_addr, usb_ctrl_reg.val);

	/* wait at least 5ms to let bus idle */
	mdelay(5);

	/* open line status detect function */
	usb_ctrl_reg.val = READREG32(reg_addr);
	usb_ctrl_reg.bits.lscd_en = 1;
	usb_ctrl_reg.bits.lsci_en = 1;
	WRITEREG32(reg_addr, usb_ctrl_reg.val);

	return ret;
}

int lb_nx_usbphy_resume(void __iomem *reg_base)
{
	int			ret = 0;
	void __iomem		*reg_addr;
	reg_usb_usbctrl_t	usb_ctrl_reg;

	reg_addr = reg_base + USBCTRL;

	usb_ctrl_reg.val = READREG32(reg_addr);
	usb_ctrl_reg.bits.lscd_en = 0;
	usb_ctrl_reg.bits.lsci_en = 0;
	usb_ctrl_reg.bits.lscd_flg = 1;

	usb_ctrl_reg.bits.susp_sel = 1;
	usb_ctrl_reg.bits.susp = 1;
	WRITEREG32(reg_addr, usb_ctrl_reg.val);

	return ret;
}

#if !IS_ENABLED(CONFIG_ARCH_LOMBO_N5)
int lb_nx_usbphy_read_efuse_ref(int id, char *value)
{
	int ret = 0;
	int data_len;
	char *buffer;

	ret = lombo_get_efuse_module_len(id, &data_len);
	if (ret) {
		pr_err("get efuse module len failed!\n");
		return -EINVAL;
	}

	buffer = kzalloc(data_len, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;

	ret = lombo_efuse_read(id, (void *)buffer, data_len);
	if (ret) {
		pr_err("efuse read failed!\n");
		ret = -EINVAL;
	} else {
		/*
		 * note:
		 * the usb efuse value valid data len: 7 bits. And
		 * one byte is enough.
		 */
		*value = buffer[0];
	}

	kfree(buffer);

	return ret;
}
#else
int lb_nx_usbphy_read_efuse_ref(int id, char *value)
{
	return 0;
}
#endif
